import XEUtils from 'xe-utils/methods/xe-utils'
import VXETable from 'vxe-table/lib/vxe-table'

function getFormatDate (value: any, props: any, defaultFormat: string) {
  return XEUtils.toDateString(value, props.format || defaultFormat)
}

function getFormatDates (values: any, props: any, separator: string, defaultFormat: string) {
  return XEUtils.map(values, (date: any) => getFormatDate(date, props, defaultFormat)).join(separator)
}

function equalDaterange (cellValue: any, data: any, props: any, defaultFormat: string) {
  cellValue = getFormatDate(cellValue, props, defaultFormat)
  return cellValue >= getFormatDate(data[0], props, defaultFormat) && cellValue <= getFormatDate(data[1], props, defaultFormat)
}

function matchCascaderData (index: number, list: Array<any>, values: Array<any>, labels: Array<any>) {
  let val = values[index]
  if (list && values.length > index) {
    XEUtils.each(list, (item: any) => {
      if (item.value === val) {
        labels.push(item.label)
        matchCascaderData(++index, item.children, values, labels)
      }
    })
  }
}

function getProps ({ $table }: any, { props }: any) {
  // return XEUtils.assign($table.vSize ? { size: $table.vSize } : {}, props)
  let p=XEUtils.assign($table.props ? $table.props : {}, props)
  return p;
}

function getCellEvents (renderOpts: any, params: any) {
  let { events } = renderOpts
  let { $table } = params
  let type = 'on-change'
  let on = {
    [type]: () => $table.updateStatus(params)
  }
  if (events) {
    XEUtils.assign(on, XEUtils.objectMap(events, (cb: Function) => function (...args: any[]) {
      cb.apply(null, [params].concat.apply(params, args))
    }))
  }
  return on
}

function defaultEditRender (h: Function, renderOpts: any, params: any) {
  let { row, column } = params
  let _params=column.params
  let { attrs } = renderOpts
  let props = getProps(params, renderOpts)
  let componentName='zInput';
  //根据控件类型不同，显示不同格式
  if(_params.componentName==='UIMeta_InputBox'){
	componentName = 'zInput';
  }else if(_params.componentName==='UIMeta_Url'){
	componentName = 'zInput';
  }else if(_params.componentName==='UIMeta_Select'){
	componentName = 'zSelect';
  }else if(_params.componentName==='UIMeta_DatePicker'){
	let placement=params.data.length>5 && params.data.length - params.$rowIndex < 5 ? 'top':'bottom';
	XEUtils.assign(props,{placement:placement})	
	componentName = 'zDatePicker';
  }else if(_params.componentName==='UIMeta_TimePicker'){
	let placement=params.data.length>5 && params.data.length - params.$rowIndex < 5 ? 'top':'bottom';
	XEUtils.assign(props,{placement:placement})	  
	componentName = 'zTimePicker';
  }else if(_params.componentName==='UIMeta_Checkbox'){
	componentName = 'zCheckbox';
  }else if(_params.componentName==='UIMeta_InputBigDecimal'){
	componentName = 'zInputNumber';
  }else if(_params.componentName==='UIMeta_InputInteger'){
	XEUtils.assign(props,{precision:0,step:1})
	componentName = 'zInputNumber';
  }else if(_params.componentName==='UIMeta_BaseDataSelect'){
	let placement=params.data.length>5 && params.data.length - params.$rowIndex < 5 ? 'top':'bottom';

	XEUtils.assign(props,{label:'number',placement:placement})	  
	componentName = 'zDataSelect';
  }
  return [
    h(componentName, {
      props,
      attrs,
      model: {
        value: XEUtils.get(row, column.property),
        callback (value: any) {
          XEUtils.set(row, column.property, value)
        }
      },
      on: getCellEvents(renderOpts, params)
    })
  ]
}

function getFilterEvents (on: any, renderOpts: any, params: any) {
  let { events } = renderOpts
  if (events) {
    XEUtils.assign(on, XEUtils.objectMap(events, (cb: Function) => function (...args: any[]) {
      cb.apply(null, [params].concat.apply(params, args))
    }))
  }
  return on
}

function defaultFilterRender (h: Function, renderOpts: any, params: any, context: any) {
  let { column } = params
  let { name, attrs } = renderOpts
  let type = 'on-change'
  let props = getProps(params, renderOpts)
  return column.filters.map((item: any) => {
    return h(name, {
      props,
      attrs,
      model: {
        value: item.data,
        callback (optionValue: any) {
          item.data = optionValue
        }
      },
      on: getFilterEvents({
        [type] () {
          handleConfirmFilter(context, column, !!item.data, item)
        }
      }, renderOpts, params)
    })
  })
}

function handleConfirmFilter (context: any, column: any, checked: any, item: any) {
  context[column.filterMultiple ? 'changeMultipleOption' : 'changeRadioOption']({}, checked, item)
}

function defaultFilterMethod ({ option, row, column }: any) {
  let { data } = option
  let cellValue = XEUtils.get(row, column.property)
  /* eslint-disable eqeqeq */
  return cellValue === data
}

function renderOptions (h: Function, options: any, optionProps: any) {
  let labelProp = optionProps.label || 'name'
  let valueProp = optionProps.value || 'number'
  return XEUtils.map(options, (item: any, index: number) => {
    return h('zOption', {
      props: {
        value: item[valueProp],
        label: item[labelProp]
      },
      key: index
    })
  })
}

function cellText (h: Function, cellValue: any) {
	
  return ['' + (cellValue === null || cellValue === void 0 ? '' : cellValue)]
}

function defaultRenderCell  (h: Function, renderOpts: any, params: any) {
	  let { row, column } = params
	  let _params=column.params;
	  let cellValue:any;
	  if(typeof column.formatter==='function'){
		  //formatter优先，如果是基础数据选择属性之类的字段，就使用formatter解决了
		  cellValue=column.formatter(row,column.property);
	  }else{
		  //根据控件类型不同，显示不同格式
		  if(_params.componentName==='UIMeta_InputBox'){
			cellValue=XEUtils.get(row, column.property);
		  }else if(_params.componentName==='UIMeta_Url'){
			cellValue=XEUtils.get(row, column.property);
			if(cellValue!==null && cellValue!==undefined){
				cellValue='<a>' + XEUtils.get(row, column.property)+'</a>';
			}else{
				cellValue='';
			}
		  }else if(_params.componentName==='UIMeta_Select'){
			//查找字典，显示名称
			cellValue=XEUtils.get(row, column.property);
		    cellValue=XEUtils.find(renderOpts.props.options,(item: any) => item.value === cellValue);
			cellValue=cellValue==null?'':cellValue.name;
		  }else if(_params.componentName==='UIMeta_DatePicker'){
			cellValue=XEUtils.get(row, column.property);
			cellValue=cellValue instanceof Date ? XEUtils.toDateString(cellValue,renderOpts.props.format):cellValue;
		  }else if(_params.componentName==='UIMeta_TimePicker'){
			cellValue=XEUtils.get(row, column.property);
			cellValue=cellValue instanceof Date ? XEUtils.toDateString(cellValue,renderOpts.props.format):cellValue;
		  }else if(_params.componentName==='UIMeta_Checkbox'){
			//特殊处理下，如果是编辑模式下，使用编辑控件，如果是显示模式，显示基础check控件
			if(column.editRender){
				return defaultEditRender(h, renderOpts, params);
			}else{
				cellValue=XEUtils.get(row, column.property);
				cellValue=cellValue? '<input type="checkbox" checked readonly/>': '<input type="checkbox" readonly/>'
			}			
		  }else if(_params.componentName==='UIMeta_InputBigDecimal'){
			cellValue=XEUtils.get(row, column.property);
			cellValue=renderOpts.props && renderOpts.props.precision ? XEUtils.toFixedString(cellValue,renderOpts.props.precision):cellValue;
		  }else if(_params.componentName==='UIMeta_InputInteger'){
			cellValue=XEUtils.get(row, column.property);
		  }else if(_params.componentName==='UIMeta_BaseDataSelect'){
			cellValue=XEUtils.get(row, column.property);
			if(cellValue && cellValue.name){
				cellValue=cellValue.name;
			}
		  }
	  }
	  let onEvent={};
	  if(typeof _params.onclick==='function'){
		  //支持定义单击事件
		  XEUtils.assign(onEvent,{click:function(){
			  return _params.onclick(row, 0, 0, column);
		  }})
	  }
	  
	  return [h("span", {
		  domProps:{
			  innerHTML: cellValue
		  },
		  on: onEvent
	    })]  
	}
/**
 * 渲染函数
 */
const renderMap = {
  UIMeta_InputBox: {
    autofocus: 'input.ivu-input',
    autoselect:false,
    renderDefault: defaultEditRender,
    renderEdit: defaultEditRender,
    renderFilter: defaultFilterRender,
    filterMethod: defaultFilterMethod,
	renderCell: defaultRenderCell
  },
  UIMeta_Url: {
    autofocus: 'input.ivu-input',
    renderDefault: defaultEditRender,
    renderEdit: defaultEditRender,
    renderFilter: defaultFilterRender,
    filterMethod: defaultFilterMethod,
	renderCell: defaultRenderCell
  },
  UIMeta_InputBigDecimal: {
    autofocus: 'input.ivu-input-number-input',
    renderDefault: defaultEditRender,
    renderEdit: defaultEditRender,
    renderFilter: defaultFilterRender,
    filterMethod: defaultFilterMethod,
	renderCell: defaultRenderCell
  },
  UIMeta_InputInteger: {
    autofocus: 'input.ivu-input-number-input',
    renderDefault: defaultEditRender,
    renderEdit: defaultEditRender,
    renderFilter: defaultFilterRender,
    filterMethod: defaultFilterMethod,
	renderCell: defaultRenderCell
  },  
  UIMeta_Checkbox: {
    renderDefault: defaultEditRender,
    renderEdit: defaultEditRender,
    renderFilter: defaultFilterRender,
    filterMethod: defaultFilterMethod,
	renderCell: defaultRenderCell
  },    
  UIMeta_BaseDataSelect: {
    autofocus: 'input.ivu-input',
    renderDefault: defaultEditRender,
    renderEdit: defaultEditRender,
    renderFilter: defaultFilterRender,
    filterMethod: defaultFilterMethod,
	renderCell: defaultRenderCell
  },
  zAutoComplete: {
    autofocus: 'input.ivu-input',
    renderDefault: defaultEditRender,
    renderEdit: defaultEditRender,
    renderFilter: defaultFilterRender,
    filterMethod: defaultFilterMethod
  },
  UIMeta_Select: {
    renderEdit (h: Function, renderOpts: any, params: any) {
      let { options, optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts
	  if(!options){
		  //兼容新模式
		  options=renderOpts.props && renderOpts.props.options?renderOpts.props.options:options;
	  }
	 if(!optionGroups){
			//兼容新模式
			optionGroups=renderOpts.optionGroups && renderOpts.props.optionGroups?renderOpts.props.optionGroups:optionGroups;
	 }
      let { row, column } = params
      let { attrs } = renderOpts
      let props = getProps(params, renderOpts)
      if (optionGroups) {
        let groupOptions = optionGroupProps.options || 'options'
        let groupLabel = optionGroupProps.label || 'name'
        return [
          h('zSelect', {
            props,
            attrs,
            model: {
              value: XEUtils.get(row, column.property),
              callback (cellValue: any) {
                XEUtils.set(row, column.property, cellValue)
              }
            },
            on: getCellEvents(renderOpts, params)
          }, XEUtils.map(optionGroups, (group: any, gIndex: number) => {
            return h('zOptionGroup', {
              props: {
                label: group[groupLabel]
              },
              key: gIndex
            }, renderOptions(h, group[groupOptions], optionProps))
          }))
        ]
      }
	  let placement=params.data.length>5 && params.data.length - params.$rowIndex < 5 ? 'top':'bottom';
	  XEUtils.assign(props,{label:'name',value:'number',placement:placement});
      return [
        h('zSelect', {
          props,
          attrs,
          model: {
            value: XEUtils.get(row, column.property),
            callback (cellValue: any) {
              XEUtils.set(row, column.property, cellValue)
            }
          },
          on: getCellEvents(renderOpts, params)
        }, renderOptions(h, options, optionProps))
      ]
    },
    renderCell (h: Function, renderOpts: any, params: any) {
      let { options, optionGroups, props = {}, optionProps = {}, optionGroupProps = {} } = renderOpts	  
      let { row, column } = params
      let labelProp = optionProps.label || 'name'
      let valueProp = optionProps.value || 'number'
      let groupOptions = optionGroupProps.options || 'options'
	  if(renderOpts.props){
	  	//兼容新模式
		if(renderOpts.props.options!==undefined){
	  		options=renderOpts.props.options;
	  	 }
	  	if(renderOpts.props.optionGroups!==undefined){
	  		optionGroups=renderOpts.props.optionGroups;
	  	}
	  	if(renderOpts.props.optionGroups!==undefined){
	  		optionGroups=renderOpts.props.optionGroups;
	  	}
	   }
	  
      let cellValue = XEUtils.get(row, column.property)
      if (!(cellValue === null || cellValue === undefined || cellValue === '')) {
        return cellText(h, XEUtils.map(props.multiple ? cellValue : [cellValue], optionGroups ? (value: any) => {
          let selectItem
          for (let index = 0; index < optionGroups.length; index++) {
            selectItem = XEUtils.find(optionGroups[index][groupOptions], (item: any) => item[valueProp] === value)
            if (selectItem) {
              break
            }
          }
          return selectItem ? selectItem[labelProp] : null
        } : (value: any) => {
          let selectItem = XEUtils.find(options, (item: any) => item[valueProp] === value)
          return selectItem ? selectItem[labelProp] : null
        }).join(';'))
      }
      return cellText(h, '')
    },
    renderFilter (h: Function, renderOpts: any, params: any, context: any) {
      let { options, optionGroups, optionProps = {}, optionGroupProps = {} } = renderOpts
	  if(!options){
	  		  //兼容新模式
	  		  options=renderOpts.props && renderOpts.props.options?renderOpts.props.options:options;
	   }
	  if(!optionGroups){
	  			//兼容新模式
	  			optionGroups=renderOpts.optionGroups && renderOpts.props.optionGroups?renderOpts.props.optionGroups:optionGroups;
	  }
	  
      let { column } = params
      let { attrs } = renderOpts
      let props = getProps(params, renderOpts)
      if (optionGroups) {
        let groupOptions = optionGroupProps.options || 'options'
        let groupLabel = optionGroupProps.label || 'name'
        return column.filters.map((item: any) => {
          return h('zSelect', {
            props,
            attrs,
            model: {
              value: item.data,
              callback (optionValue: any) {
                item.data = optionValue
              }
            },
            on: getFilterEvents({
              'on-change' (value: any) {
                handleConfirmFilter(context, column, value && value.length > 0, item)
              }
            }, renderOpts, params)
          }, XEUtils.map(optionGroups, (group: any, gIndex: number) => {
            return h('OptionGroup', {
              props: {
                label: group[groupLabel]
              },
              key: gIndex
            }, renderOptions(h, group[groupOptions], optionProps))
          }))
        })
      }
      return column.filters.map((item: any) => {
        return h('zSelect', {
          props,
          attrs,
          model: {
            value: item.data,
            callback (optionValue: any) {
              item.data = optionValue
            }
          },
          on: getFilterEvents({
            'on-change' (value: any) {
              handleConfirmFilter(context, column, value && value.length > 0, item)
            }
          }, renderOpts, params)
        }, renderOptions(h, options, optionProps))
      })
    },
    filterMethod ({ option, row, column }: any) {
      let { data } = option
      let { property, filterRender: renderOpts } = column
      let { props = {} } = renderOpts
      let cellValue = XEUtils.get(row, property)
      if (props.multiple) {
        if (XEUtils.isArray(cellValue)) {
          return XEUtils.includeArrays(cellValue, data)
        }
        return data.indexOf(cellValue) > -1
      }
      /* eslint-disable eqeqeq */
      return cellValue == data
    }
  },
  zCascader: {
    renderEdit: defaultEditRender,
    renderCell (h: Function, { props = {} }: any, params: any) {
      let { row, column } = params
      let cellValue = XEUtils.get(row, column.property)
      let values = cellValue || []
      let labels: Array<any> = []
      matchCascaderData(0, props.data, values, labels)
      return cellText(h, labels.join(` ${props.separator || '/'} `))
    }
  },
  UIMeta_DatePicker: {
    // autofocus: 'input.ivu-input',
    renderEdit: defaultEditRender,
	renderCell: defaultRenderCell,
    // renderCell (h: Function, { props = {} }: any, params: any) {
    //   let { row, column } = params
    //   let { separator } = props
    //   let cellValue = XEUtils.get(row, column.property)
    //   switch (props.type) {
    //     case 'week':
    //       cellValue = getFormatDate(cellValue, props, 'yyyywWW')
    //       break
    //     case 'month':
    //       cellValue = getFormatDate(cellValue, props, 'yyyy-MM')
    //       break
    //     case 'year':
    //       cellValue = getFormatDate(cellValue, props, 'yyyy')
    //       break
    //     case 'dates':
    //       cellValue = getFormatDates(cellValue, props, ', ', 'yyyy-MM-dd')
    //       break
    //     case 'daterange':
    //       cellValue = getFormatDates(cellValue, props, ` ${separator || '-'} `, 'yyyy-MM-dd')
    //       break
    //     case 'datetimerange':
    //       cellValue = getFormatDates(cellValue, props, ` ${separator || '-'} `, 'yyyy-MM-dd HH:ss:mm')
    //       break
    //     default:
    //       cellValue = getFormatDate(cellValue, props, 'yyyy-MM-dd')
    //       break
    //   }
    //   return cellText(h, cellValue)
    // },
    renderFilter (h: Function, renderOpts: any, params: any, context: any) {
      let { column } = params
      let { attrs } = renderOpts
      let props = getProps(params, renderOpts)
      return column.filters.map((item: any) => {
        return h(renderOpts.name, {
          props,
          attrs,
          model: {
            value: item.data,
            callback (optionValue: any) {
              item.data = optionValue
            }
          },
          on: getFilterEvents({
            'on-change' (value: any) {
              handleConfirmFilter(context, column, !!value, item)
            }
          }, renderOpts, params)
        })
      })
    },
    filterMethod ({ option, row, column }: any) {
      let { data } = option
      let { filterRender: renderOpts } = column
      let { props = {} } = renderOpts
      let cellValue = XEUtils.get(row, column.property)
      if (data) {
        switch (props.type) {
          case 'daterange':
            return equalDaterange(cellValue, data, props, 'yyyy-MM-dd')
          case 'datetimerange':
            return equalDaterange(cellValue, data, props, 'yyyy-MM-dd HH:ss:mm')
          default:
            return cellValue === data
        }
      }
      return false
    }
  },
  UIMeta_TimePicker: {
    // autofocus: 'input.ivu-input',
	renderCell: defaultRenderCell,
    renderDefault: defaultEditRender,
    renderEdit: defaultEditRender,
    renderFilter: defaultFilterRender,
    filterMethod: defaultFilterMethod
  },
  UIMeta_BaseDataSelectProperty: {
	renderCell: defaultRenderCell,
    renderDefault: defaultRenderCell,
    renderEdit: defaultRenderCell,
    renderFilter: defaultFilterRender,
    filterMethod: defaultFilterMethod
  },
  zRate: {
    renderDefault: defaultEditRender,
    renderEdit: defaultEditRender,
    renderFilter: defaultFilterRender,
    filterMethod: defaultFilterMethod
  },
  zMySwitch: {
    renderDefault: defaultEditRender,
    renderEdit: defaultEditRender,
    renderFilter: defaultFilterRender,
    filterMethod: defaultFilterMethod
  }
}

/**
 * 事件兼容性处理
 */
function handleClearEvent (params: any, evnt: any, context: any) {
  let { getEventTargetNode } = context
  let bodyElem = document.body
  if (
    // 下拉框、日期
    getEventTargetNode(evnt, bodyElem, 'ivu-select-dropdown').flag
  ) {
    return false
  }
}

/**
 * 基于 vxe-table 表格的适配插件，用于兼容 iview 组件库
 */
export const VXETablePluginIView = {
  install (xtable: typeof VXETable) {
    let { interceptor, renderer } = xtable
    renderer.mixin(renderMap)
    interceptor.add('event.clearFilter', handleClearEvent)
    interceptor.add('event.clearActived', handleClearEvent)
  }
}

if (typeof window !== 'undefined' && window.VXETable) {
  window.VXETable.use(VXETablePluginIView)
}

export default VXETablePluginIView
